#ifndef _CELLACCESS_H_
#define _CELLACCESS_H_

#include "iteratestrategy.h"
//#include "uncopyable.h"
#include "cell.h"
#include "grid.h"
#include "tetrahedron.h"
#include "hexahedron.h"
#include "pyramid.h"
#include "prism.h"

#include <algorithm>

#include <vector>

namespace visualization
{
class UnstructuredGrid;
class Tetrahedron;
class Hexahedron;
class Pyramid;
class Prism;
class Cell3D;
class Point;

enum CellType;

class CellAccess// : public Uncopyable
{
//	friend class UnstructuredGrid;
	friend class PointIDMapper;

private:
	class PointIDMapper
	{
	public:
		CellAccess *server;
		size_t operator()(size_t &dest) const;
	};

	UnstructuredGrid *server;

	size_t total;
	size_t cell_id;
	size_t point_num;
	size_t offset;

	Cell3D *current_cell;
	PointIDMapper id_mapper;
	IterateStrategy *is;
	std::vector<size_t> *cells;

	Tetrahedron *tet;
	Hexahedron  *hex;
	Pyramid     *pry;
	Prism       *pri;


	void GetCurrentCellHandler();

public:
	CellAccess();
	CellAccess(UnstructuredGrid *grid, size_t id);
	~CellAccess();

	const PointIDMapper & GetPointIDMapper()
	{
		return id_mapper;
	}

	size_t CellID()
	{
		return cell_id;
	}

	bool IsDone()
	{
		return cell_id == total;
	}

	void Next()
	{
		cell_id ++;
		Sycronize();
	}

	void SetIterateStrategy(IterateStrategy *is)
	{
		this->is = is;
		is->server = this;
		is->GetReady();
	}

	bool Iterate()
	{
		cell_id = is->Next();
		return Sycronize();
	}

	bool Sycronize();

	Point * GetPoint(size_t i);

	CellType GetFacet(size_t i, size_t *point_ids);

	//Point GetBerycenter()
	//{
	//	return current_cell->GetBeryCenter();
	//}
};

}

#endif

